package com.apes.fn.scm.retailOrder.service.orderFix;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderDiscount;
import com.apes.fn.scm.retailOrder.model.RetailOrderDiscountItem;
import com.apes.fn.scm.retailOrder.model.RetailOrderItem;
import com.apes.fn.scm.retailOrder.repository.RetailOrderDiscountItemRepository;
import com.apes.fn.scm.retailOrder.repository.RetailOrderDiscountRepository;
import com.apes.fn.scm.retailOrder.repository.RetailOrderItemRepository;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.repository.VoucherRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.awt.print.Pageable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author wuq
 * @Date 2021-8-27
 */
@Service
public class RetailOrderDataHandler extends DomainService {

    @Autowired
    private RetailOrderDiscountRepository retailOrderDiscountRepository;
    @Autowired
    private RetailOrderDiscountItemRepository retailOrderDiscountItemRepository;
    @Autowired
    private VoucherRepository voucherRepository;
    @Autowired
    private ServicePlanItemRepository servicePlanItemRepository;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private RetailOrderItemRepository retailOrderItemRepository;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private RetailOrderRepository retailOrderRepository;

    public Map findOrderById(SimpleRequest request) {
        Map<String, Object> map = new HashMap<>();
        String id = request.get("id");
        RetailOrder retailOrder = retailOrderRepository.findOne(id);
        if (retailOrder == null) throw new RuntimeException("传入的零售单有误，未找到对应的数据！");

        // 主表数据
        map = MapUtil.mapper("id", retailOrder.getId(), "origin", retailOrder.getOrigin(), "source", retailOrder.getSource(),
                "amtTotal", retailOrder.getAmtTotal(), "carLicense", retailOrder.getCustomerExpand().getCarLicense(),
                "dept", MapUtil.mapper("id", retailOrder.getDept().getId(), "name", retailOrder.getDept().getName()),
                "company", MapUtil.mapper("id", retailOrder.getCompany().getId(), "name", retailOrder.getCompany().getName()));

        // 明细数据
        List<String> discountIds = new ArrayList<>();
        List<Map<String, Object>> saleItems = new ArrayList<>();
        retailOrder.getSaleItems().forEach( item -> {
            Map<String, Object> saleItemMap = new HashMap<>();
            saleItemMap.put("product", MapUtil.mapper("id", item.getProduct().getId(), "name", item.getProduct().getName()));

            List<Map<String, Object>> discountLists = new ArrayList<>();
            item.getRetailDiscounts().forEach( retailOrderDiscount -> {
                Map<String, Object> discountMap = new HashMap<>();
                discountMap.put("discountId", retailOrderDiscount.getId());
                discountMap.put("discountAmount", retailOrderDiscount.getDiscountAmount());
                discountMap.put("couponDiscountAmount", retailOrderDiscount.getCouponDiscountAmount());
                discountMap.put("couponResource", retailOrderDiscount.getCouponResource());
                discountLists.add(discountMap);

                discountIds.add(retailOrderDiscount.getId());
            });
            saleItemMap.put("retailDiscounts", discountLists);
            saleItems.add(saleItemMap);
        });

        map.put("saleItems", saleItems);
        map.put("discountIds", discountIds);
        return map;
    }

    /**
     * 实现通过ID查询方案号/第三方系统号/零售单号/源单号
     * @param request
     * @return
     */
    public Page<RetailOrder> findAllByIdOrAppOrder(SimpleRequest request){
        List<Map> filters = request.get("condition");
        Page<RetailOrder> result = retailOrderRepository.findAll(JpaDsl.toCriteria(filters),
                PageRequest.of(request.get("page"), request.get("size")
                        , new Sort(Sort.Direction.ASC, "id")));
        List<Map> id = filters.stream().filter(map -> map.get("field").equals("id")).collect(Collectors.toList());
        if (id.isEmpty())return result;
        if (!result.getContent().isEmpty())return result;
        //查询源编码
        List<RetailOrder> content = new ArrayList<>();
        content.addAll(result.getContent());
        filters = filters.stream().map(map -> {
            if (map.get("field").equals("id")) map.put("field", "origin");
            return map;
        }).collect(Collectors.toList());
        Page<RetailOrder> result2 = retailOrderRepository.findAll(JpaDsl.toCriteria(filters),
                PageRequest.of(request.get("page"), request.get("size")
                        , new Sort(Sort.Direction.ASC, "id")));
        content.addAll(result2.getContent());

        if (!content.isEmpty())return new PageImpl<RetailOrder>(content, result.getPageable(), content.size());
        //查询来源编码
        filters = filters.stream().map(map -> {
            if (map.get("field").equals("origin")) map.put("field", "source");
            return map;
        }).collect(Collectors.toList());
        Page<RetailOrder> result3 = retailOrderRepository.findAll(JpaDsl.toCriteria(filters),
                PageRequest.of(request.get("page"), request.get("size")
                        , new Sort(Sort.Direction.ASC, "id")));
        content.addAll(result3.getContent());

        return new PageImpl<RetailOrder>(content, result.getPageable(), content.size());
    }

    public void saveForList(SimpleRequest simpleRequest){
        JSONArray array = simpleRequest.getJA();
        if (array.size() == 0) return;

        array.forEach( x -> {
            JSONObject json = (JSONObject) x;
            create(json);
        });
    }

    public RetailOrderDiscountItem saveForSingle(SimpleRequest simpleRequest){
        JSONObject json = simpleRequest.getJO();

        return create(json);
    }

    private RetailOrderDiscountItem create(JSONObject json) {
        RetailOrderDiscountItem retailOrderDiscountItem = new RetailOrderDiscountItem();
        retailOrderDiscountItem.setRetailOrderId(json.getString("retailOrderId"));
        retailOrderDiscountItem.setAmount(json.getDouble("amount"));

        if (StringUtils.isEmpty(json.getString("deptId") )) throw new RuntimeException("没有传入者部门字段！");
        Dept dept = deptRepository.findById(json.getString("deptId"))
                .orElseThrow(() ->  new RuntimeException("根据传入的部门编码，没有找到对应的部门：" + json.getString("deptId")));
        retailOrderDiscountItem.setDept(dept);

        RetailOrderDiscount retailDiscount = retailOrderDiscountRepository.findById(json.getString("discountId"))
                .orElseThrow( () -> new RuntimeException("根据传入的折扣明细，没有对应的数据：" + json.getString("discountId")));
        retailOrderDiscountItem.setRetailDiscount(retailDiscount);

        return retailOrderDiscountItemRepository.saveAndFlush(retailOrderDiscountItem);
    }


    /**
     * 内协凭证重新生成，以及结转凭证
     * 原因：内协采购为 0元
     */
    public Map updateMaintenanceVoucher(SimpleRequest request){
        String id = request.get("id");
        Voucher newVoucher = new Voucher();
        Voucher oldVoucher = voucherRepository.findOne(id);

        ReflectUtil.copy(oldVoucher, newVoucher,
                "dept", "company", "partner", "contract", "voucherType", "businessType",
                "inventoryMode", "accountingMethod",
                "scene", "clerk", "classification", "customerExpand",
                "originBusinessType", "origin", "sourceBusinessType", "source");

        newVoucher.setVoucherItems(
                oldVoucher.getVoucherItems().stream().map(
                        items -> {
                            VoucherItem voucherItem = new VoucherItem();
                            ReflectUtil.copy(items, voucherItem,"product", "tax", "productQty", "uom", "sourceItemId", "originItemId");

                            ServicePlanItem servicePlanItem = servicePlanItemRepository.findOne(voucherItem.getOriginItemId());
                            voucherItem.setPriceUnit(servicePlanItem.getPlatformPriceCosInTax());
                            voucherItem.setPriceTotal(voucherItem.getPriceUnit() * voucherItem.getProductQty());

                            return voucherItem;
                        }).collect(Collectors.toSet()));

        newVoucher = invoke("voucher.create", MapUtil.mapped(newVoucher));

        sendBathAndSupplierEvent(newVoucher);

        invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(newVoucher))));
        return MapUtil.mapped(newVoucher);
    }

    /**
     * 发送事件回写方案的数据
     *
     * @param voucher 凭证信息
     */
    private void sendBathAndSupplierEvent(Voucher voucher) {
        voucher.getVoucherItems().stream()
                .forEach(voucherItem -> {
                    VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(voucherItem).stream().findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));
                    InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();

                    // 冻结批次数量
                    inventoryService.changeFrostQty(inventoryBatch, inventoryBatch.getUom(),inventoryBatch.getPurchaseQty(),voucher.getCompany(),voucher.getInnerBusinessType(),voucher.getId(), String.valueOf(voucherItem.getId()),"发送事件回写方案的数据");

                    ServicePlanItem servicePlanItem = servicePlanItemRepository.findOne(voucherItem.getOriginItemId());
                    RetailOrderItem retailOrderItem = retailOrderItemRepository.findAll(JpaDsl.toCriteriaByEq("originnumber", voucherItem.getOriginItemId()))
                            .stream().findFirst().get();


                    servicePlanItem.setInventoryBatch(inventoryBatch);
                    servicePlanItemRepository.save(servicePlanItem);

                    retailOrderItem.setInventoryBatch(inventoryBatch);
                    retailOrderItemRepository.save(retailOrderItem);
                });
    }
}
